﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Data.SqlClient;
using Player.MyAttribute;
using System.Reflection;

namespace Player
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public static string ConnectionString = "Data Source=HUNK\\DIRECTAUDIT3;Initial Catalog=1234;Integrated Security=True";
        public static string SessionId = "31c86d7c-8987-4947-be38-b94bd6627fdd";

        public static int Count = 0;

        public App()
        {
            //TInput input = new TInput();
            //input.Age = 10;
            //input.Name = 20;
            //input.Sex = "30";
            //Parameters(input);
            TInput input = new TInput();
            foreach (var field in typeof(TInput).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                object val = typeof(TInput).InvokeMember(field.Name,
                                                         BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                                                         null, input, null);
             SqlParameter p= new SqlParameter("@TT", val);
             SetSqlDbTypeForNullValue(p, field.GetType());
                   
            }

        }

        //public enum Variables : int
        //{
        //    [Variable(Direction.Input)]
        //    SessionId,
        //    [Variable(Direction.Input)]
        //    AuditDatabaseId,
        //    [Variable(Direction.Output)]
        //    PixelFormat,
        //    [Variable(Direction.Output)]
        //    Palette,
        //    [Variable(Direction.Output)]
        //    User,
        //    [Variable(Direction.Output)]
        //    StartTime,
        //    [Variable(Direction.Output)]
        //    TimeStampOffSet,
        //    [Variable(Direction.Output)]
        //    Machine
        //}

        private void SetSqlDbTypeForNullValue(SqlParameter parameter, Type valueType)
        {
            // System.ComponentModel.TypeConverter.ConvertFrom() is not used as it is forbidden in CLR Stored Proc
            SqlDbType resultDbType = parameter.SqlDbType;
            int resultSize = parameter.Size;
            object resultValue = parameter.Value;

            if (resultValue == null)
            {
                // Only handle varchar(max), varbinary(max) for which optional stored proc parameter is not supported
                if (valueType == Type.GetType("System.Byte[]"))
                {
                    resultDbType = SqlDbType.VarBinary;
                    resultSize = int.MaxValue;
                    resultValue = DBNull.Value;
                }
                else if (valueType == typeof(string))
                {
                    resultDbType = SqlDbType.VarChar;
                    resultSize = int.MaxValue;
                    resultValue = DBNull.Value;
                }

                parameter.SqlDbType = resultDbType;
                parameter.Size = resultSize;
                parameter.Value = resultValue;
            }
        }
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            Application.Current.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(Current_DispatcherUnhandledException);
        }

        void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            MessageBox.Show("Current_DispatcherUnhandledException");
        }

        static SqlParameter[] Parameters(TInput input)
        {
            Dictionary<int, SqlParameter> parameters = new Dictionary<int, SqlParameter>();

            // Add all the parameters from Input struct with the initialied values
            foreach (FieldInfo field in typeof(TInput).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                InputMappingAttribute attr = Attribute.GetCustomAttribute(field, typeof(InputMappingAttribute)) as InputMappingAttribute;
                if (attr == null) throw new Exception("Fields in Input struct should have InputMapping attribute mapped to the variables");
                //if (parameters.ContainsKey(attr.Variable)) throw new Exception(string.Format("Variable '{0}' is already mapped by another field", (TVariables)(Object)attr.Variable));

                object val = typeof(TInput).InvokeMember(field.Name,
                    BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    null, input, null);
                //parameters[attr.Variable] = new SqlParameter("@" + (TVariables)(object)attr.Variable, val);

                //// For parameter input value is null, we need to define the value type for the SqlParemeter, 
                //// and change its value to DBNull.Value
                //if (val == null)
                //{
                //    SetSqlDbTypeForNullValue(parameters[attr.Variable], field.FieldType);
                //}
            }
            return null;

            // Add all the parameters from Output class
            //foreach (FieldInfo field in typeof(TOutput).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            //{
            //    OutputMappingAttribute attr = Attribute.GetCustomAttribute(field, typeof(OutputMappingAttribute)) as OutputMappingAttribute;
            //    if (attr != null)
            //    {
            //        if (parameters.ContainsKey(attr.Variable)) throw new Exception(string.Format("Variable '{0}' is already mapped by another field", (TVariables)(Object)attr.Variable));
            //        SqlParameter parameter = new SqlParameter("@" + (TVariables)(object)attr.Variable, attr.DbType, attr.Size);

            //        parameter.Direction = ParameterDirection.Output;
            //        parameters[attr.Variable] = parameter;
            //    }
            //}

            //// Do the checking to make sure the defined variables are mapped by either Input class or Output class
            //FieldInfo[] variables = typeof(TVariables).GetFields(BindingFlags.Public | BindingFlags.Static);
            //foreach (FieldInfo variable in variables)
            //{
            //    int key = (int)variable.GetRawConstantValue();
            //    if (!parameters.ContainsKey(key)) throw new Exception(string.Format("Variable '{0}' is not mapped", variable.Name));

            //    SqlParameter parameter = parameters[key];
            //    VariableAttribute attr = Attribute.GetCustomAttribute(variable, typeof(VariableAttribute)) as VariableAttribute;

            //    bool inputDirection = true; // No attribute means input direction
            //    if (attr != null && attr.Direction == Direction.Output) inputDirection = false;

            //    if (inputDirection && parameter.Direction == ParameterDirection.Output)
            //    {
            //        throw new Exception(string.Format("Variable '{0}' is mapped to Output struct.  It should be mapped to Input struct", variable.Name));
            //    }
            //    else if (!inputDirection && parameter.Direction == ParameterDirection.Input)
            //    {
            //        throw new Exception(string.Format("Variable '{0}' is mapped to Input struct.  It should be mapped to Output struct", variable.Name));
            //    }
            //}

            //List<SqlParameter> ret = new List<SqlParameter>();
            //foreach (SqlParameter parameter in parameters.Values)
            //{
            //    ret.Add(parameter);
            //}

            //return ret.ToArray();
        }


        struct TInput
        {
            [InputMapping(1)]
            public double Age;
            //[InputMapping(2)]
            //public int Name;
            //[InputMapping(3)]
            //public string Sex;

            //public string[] strings;
            public byte[] strings;
        }
    }
}
